/* VKOS_Thor
     * Lighting controller for 8pc acoustic drum kit, using piezos to trigger.
     [Configuration is modified via serial from host control system (RPi)]
     
     * Anything involving ShiftPWM must be handled here in the main class.
       - For some reason, it goes all fucky if we try to put it in
         an object class... It makes this kinda cluttered, but it works.
*/



// Includes
#include <string.h>
#include "Serial_Thor.h

// ShiftPWM
const int ShiftPWM_latchPin=8;       // ST_CP
#define SHIFTPWM_NOSPI   // Mandatory for ShiftPWM lib; Must define here
const int ShiftPWM_dataPin = 11;    // DS
const int ShiftPWM_clockPin = 12;   // SH_CP
const bool ShiftPWM_invertOutputs = false; 
const bool ShiftPWM_balanceLoad = false;
#include <ShiftPWM.h> // Needs to be declared after pins
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
unsigned int numRegisters = 3;
unsigned int numRGBleds = numRegisters*8/3;


// Globals
unsigned int NUM_TRIGGERS = 8;                   // Number of trigger inputs
unsigned int rtT[] = {0,0,0,0,0,0,0,0};          // Real-Time levels
unsigned int thT[] = {80,80,80,80,80,80,80,80};  // Trigger threshold levels

// Timer management
typedef struct {
  private:
    boolean bActive[] = {false, false, false, false, false, false, false, false};
    unsigned long t[] = {0,0,0,0,0,0,0,0};  // Drum light timers
  
  public:
    // getTime(i): Return the current value of timer 'i'
    //   i = Timer index
    unsigned long getTime(unsigned int i) {
      if(i<NUM_TRIGGERS) {return this->t[i];}
    }
    
    // resetAll(): Reset all timers
    void resetAll() {
      for(unsigned int r=0; r<NUM_TRIGGERS; r++) {this->t[r] = 0;}
    }
    
    // start(i): Reset and start incrementing timer 'i'
    void start(unsigned int i) {
      if(i<NUM_TRIGGERS) {this->t[i] = 0;}    // Reset timer
    }
    
    // tick(i): Increment all active timers
    void tick() {
      for(unsigned int t=0; t<NUM_TIMERS; t++) {
        if(this->bActive[t]) {this->t[i]++;}  // If timer is active, increment.
      }
    }    
} objTimeManager;
objTimeManager TIMEMAN = new objTimeManager();


int iA0=0; boolean bD0=false; int iD0s=0;
int iD0StartTime=0;



void setup() {
  Serial.begin(115200);  // Python access from RPi
  //InitializeLightRig(); // Call this first, or shit will get ugly.
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.Start(pwmFrequency,maxBrightness);
  ShiftPWM.SetPinGrouping(1);
  ShiftPWM.SetAll(0);
  ShiftPWM.SetRGB(0,255,255,255);
  ShiftPWM.SetRGB(1,255,0,255);
}

void loop() {
  //getMessage(); // Check for serial activity
  ckD0();
  flashD0();
  delay(10);
}

void ckD0() {
  iA0 = analogRead(0);
  if(!bD0) { // Light is off, fade in then out
    if(iA0>30) { // Check threshold
      bD0 = true; iD0s = 0; iD0StartTime=0; // Reset fade
      flashD0();
    }
  } 
    //}
  //}
  //else { // Handle brightness adjustment for fade
  //  ShiftPWM.SetOne(1,iD0s);
}
  
void flashD0() {
  unsigned char brightness;
  unsigned long fadeTime = 250;
  unsigned long loopTime = fadeTime*2;
  unsigned long time = millis()-iD0StartTime;
  unsigned long timer = time%loopTime;
  unsigned long currentStep = timer%(fadeTime*2);
  int activeLED = 0;
  
  if(currentStep <= fadeTime ){
    brightness = currentStep*maxBrightness/fadeTime; ///fading in
  }
  else{
    brightness = maxBrightness-(currentStep-fadeTime)*maxBrightness/fadeTime; ///fading out;
    if(brightness<12) {ShiftPWM.SetAll(0); bD0 = false;}
  }
  
  if(bD0) {
  ShiftPWM.SetOne(activeLED, brightness);}
}
